package cn.big.bigd.ybp.service;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.*;
import javax.validation.ValidationException;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import cn.big.bigd.ybp.dao.YbpRoleDAO;
import cn.big.bigd.ybp.dao.YbpUserDAO;
import cn.big.bigd.ybp.model.YbpRole;
import cn.big.bigd.ybp.model.YbpUser;

/**
 * 
 * @author wangfan
 *
 */
@Service
public class YbpUserService implements UserDetailsService {

    @Autowired
    private YbpUserDAO ybpUserDAO;

    @Autowired
    private YbpRoleDAO ybpRoleDAO;

    @Autowired
    PasswordEncoder passwordEncoder;

/*    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        if (ybpUserDAO.existsByUsername(s)) {
            return ybpUserDAO.findByUsername(s);
        } else {
            throw new UsernameNotFoundException(String.format("User %s not found.", s));
        }
    }*/
    
    /**
     * 获取用户对应权限
     * @param lists
     * @return
     */
    public String RoleListString(List<YbpRole> lists) {  
        List<String> authorities = new ArrayList<String>();  
        for(YbpRole role : lists) {  
            authorities.add(role.getRole());
        }  
        return StringUtils.join(authorities, ",");  
    }  
    /**
     * spring security 处理登陆
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws BadCredentialsException {
    	YbpUser user = ybpUserDAO.findByEmail(username);
    	if (user == null) {
			throw new BadCredentialsException("用户名或密码错误");
		}
        if(user.getStatus()==0){
            throw new BadCredentialsException("Email： " + username+ " 没有激活");
        }
    	 List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();

        for(YbpRole role : user.getRoleList()){
            authorities.add(new SimpleGrantedAuthority(role.getRole()));
        }

    	 
		// SecurityUser实现UserDetails并将SUser的Email映射为username
    	  return new org.springframework.security.core.userdetails.User(user.getEmail(),
                  user.getPassword(), authorities);

    }



    /**
     * 对用户密码进行加密
     * @param user
     * @return
     */
    private YbpUser encodePassword(YbpUser user) {
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        return user;
    }
    /**
     * 匹配密码
     * @param rawPassword
     * @param encodedPassword
     * @return
     */
    public  boolean passwordMatch(CharSequence rawPassword, String encodedPassword) {
    	return passwordEncoder.matches(rawPassword,encodedPassword);
 
    }
    /**
     * 对字符串加密
     * @param str
     * @return
     */
    public String encode(String str) {
        
        return passwordEncoder.encode(str);
    }
    
    /**
     * 创建管理员用户
     * @param username
     * @param password
     */

    public void createAdminUser(String email,String username, String password){
    	YbpUser user = new YbpUser();
    	user.setEmail(email);
        user.setUsername(username);
        user.setPassword(password);
        user.addRole(YbpRole.ADMIN);
        encodePassword(user);
        ybpUserDAO.save(user);
    }
    
 

    public long count() {
        return ybpUserDAO.count();
    }

    public YbpUser save(YbpUser user) {
        return ybpUserDAO.save(user);
    }

    public YbpUser createUser(YbpUser user, Integer[] roleIds) {
        encodePassword(user);
        for(Integer roleId : roleIds){
            user.addRole(ybpRoleDAO.findOne(roleId));
        }
        return ybpUserDAO.save(user);
    }

    public List<YbpUser> findAll(){
        return ybpUserDAO.findAll();
    }

    public YbpUser findByUsername(String username){
        return ybpUserDAO.findByUsername(username);
    }

    public YbpUser findById(Long id){
        return ybpUserDAO.findOne(id);
    }

    public void deleteById(Long id){
        ybpUserDAO.delete(id);
    }

    public YbpUser findByFirstNameAndLastName(String firstName, String lastName) {
        return ybpUserDAO.findByFirstNameAndLastName(firstName, lastName);
    }

    public void changePassword(String password, String newPassword, String confirmPassword, Long id) throws IllegalAccessException {
        YbpUser user = this.findById(id);

        if(!newPassword.equals(confirmPassword)){
            throw new ValidationException();
        }

        if(!passwordEncoder.matches(password, user.getPassword())){
            throw new ValidationException();
        }

        user.setPassword(passwordEncoder.encode(newPassword));
        this.save(user);
        Authentication authentication = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    public List<YbpUser> findByUserTypeAndDepartment(String userType,  String department){
        return ybpUserDAO.findByUserTypeAndDepartment(userType,department);
    }

 /*   public int updatePicPath(String picPath, Long id){
        return ybpUserDAO.updatePicPath(picPath, id);
    }*/
    
    
    public void createTempUser(String email, String password,Integer status){
    	YbpUser user = new YbpUser();
        user.setEmail(email);
        user.setPassword(password);
        user.setStatus(status);
        user.addRole(YbpRole.ADMIN);
       // System.out.println(email + password + passwordEncoder.encode(user.getPassword()));
        encodePassword(user);
        ybpUserDAO.save(user);
    }
    
    public void createTempUser(YbpUser user){

        ybpUserDAO.save(user);
    }
    /**
     * 根据邮箱找用户
     * @param email
     * @return
     */
    public YbpUser findByEmail(String email){
    	 return ybpUserDAO.findByEmail(email);
    }
    /**
     * 
     * @param status
     * @return
     */
    
    public Long countByStatus(Integer status){
   	 return ybpUserDAO.countByStatus(status);
    }
    public Long countByThirteenLunch(Integer thirteenLunch){
      	 return ybpUserDAO.countByStatusAndThirteenLunch(2,thirteenLunch);
       }
    public Long countByTwelveDinner(Integer twelveDinner){
      	 return ybpUserDAO.countByStatusAndTwelveDinner(2,twelveDinner);
       }
    public Long countByThirteenDinner(Integer thirteenDinner){
      	 return ybpUserDAO.countByStatusAndThirteenDinner(2,thirteenDinner);
       }
    
    
    public List<YbpUser> findByStatus(Integer status){
    	 return ybpUserDAO.findByStatus(status);
    }
    public List<YbpUser> findByStatusOrderByUsernameAsc(Integer status){
        return ybpUserDAO.findByStatusOrderByUsernameAsc(status);
    }

    public List<YbpUser> findByStatusAndUserTypeOrderByUsernameAsc(Integer status,String userType){
        return ybpUserDAO.findByStatusAndUserTypeOrderByUsernameAsc(status,userType);
    }

    public List<YbpUser> findByStatusAndUserTypeNotOrderByUsernameAsc(Integer status,String userType){
        return ybpUserDAO.findByStatusAndUserTypeNotOrderByUsernameAsc(status,userType);
    }


    public List<YbpUser> findByStatusAndUserTypeAndIssueNotNullOrderByUsernameAsc(Integer status,String userType){
        return ybpUserDAO.findByStatusAndUserTypeAndIssueNotNullOrderByUsernameAsc(status,userType);
    }
    
    public List<YbpUser> findByStatusAndThirteenLunch(Integer status,Integer thirteenLunch){
   	 return ybpUserDAO.findByStatusAndThirteenLunch(status, thirteenLunch);
   }
    public List<YbpUser> findByStatusAndTwelveDinner(Integer status,Integer twelveDinner){
      	 return ybpUserDAO.findByStatusAndTwelveDinner(status,twelveDinner);
      }
    
    public List<YbpUser> findByStatusAndThirteenDinner(Integer status,Integer thirteenDinner){
     	 return ybpUserDAO.findByStatusAndThirteenDinner(status,thirteenDinner);
     }
    
    /**
     * 根据token和激活状态找用户
     * @param status
     * @param token
     * @return
     */
    public YbpUser findByStatusAndToken(Integer status,String token){
    	 return ybpUserDAO.findByStatusAndToken(status,token);
    }
    /**
     * 根据email和激活状态找用户
     * @param email
     * @return
     */
    public YbpUser findByEmailAndStatus(String email,Integer status){
    	 return ybpUserDAO.findByEmailAndStatus(email,status);
    }
    /**
     * 更新激活状态
     * @param status
     * @param id
     * @return
     */
    public int updatePicPath(String picPath, Long id){
   	 return ybpUserDAO.updatePicPath(picPath,id);
   }
    /**
     * 更新激活状态
     * @param status
     * @param id
     * @return
     */
    public int updateStatus(Integer status,Long id){
   	 return ybpUserDAO.updateStatus(status,id);
   }

    public List<YbpUser> multiQuery(final String status, final String twelveDinner, final String thirteenDinner, final String thirteenLunch, final String isInvited, final String userType){
        return ybpUserDAO.findAll(new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                Predicate predicate = cb.conjunction();
                List<Expression<Boolean>> expressions = predicate.getExpressions();

                if (!org.springframework.util.StringUtils.isEmpty(status)){
                    expressions.add(cb.equal(root.get("status"), status));
                }
                if (!org.springframework.util.StringUtils.isEmpty(twelveDinner)){
                    expressions.add(cb.equal(root.get("twelveDinner"), twelveDinner));
                }
                if (!org.springframework.util.StringUtils.isEmpty(thirteenDinner)){
                    expressions.add(cb.equal(root.get("thirteenDinner"), thirteenDinner));
                }
                if (!org.springframework.util.StringUtils.isEmpty(thirteenLunch)){
                    expressions.add(cb.equal(root.get("thirteenLunch"), thirteenLunch));
                }
                if (!org.springframework.util.StringUtils.isEmpty(isInvited)){
                    expressions.add(cb.equal(root.get("isInvited"), isInvited));
                }
                if (!org.springframework.util.StringUtils.isEmpty(userType)){
                    expressions.add(cb.equal(root.get("userType"), userType));
                }
                return predicate;
            }
        });
    }
}
